package websocket;

import java.util.ArrayList;

import org.json.JSONException;
import org.json.JSONObject;

import com.example.websocket.MainActivity;

import de.tavendo.autobahn.WebSocketConnection;
import de.tavendo.autobahn.WebSocketException;
import de.tavendo.autobahn.WebSocketHandler;
import android.content.Context;
import android.os.Message;
import android.util.Log;

public class websocket_adapter 
{
	private Context m_context = null;
	private static websocket_adapter m_instance = null;
	private WebSocketConnection m_wsc = null;
	private http_interface m_http = new http_interface();
	private String m_session_id = "";
	private ws_login_req m_login_req = null;
	private ws_ans m_login_res = null;
	private ArrayList<notify_node> m_state_changed_client_list = new ArrayList<notify_node>();
	private status m_status = status.disconnected;
	private ArrayList<notify_node> m_conncet_req_client_list = new ArrayList<notify_node>();
	private static String ws_address = "ws://test.komugi-office.com:8080/knowledge/ws/servcie";
	private String m_current_name = null;
	private String m_current_pass = null;
	private WebSocketHandler m_ws_handler = new WebSocketHandler()
	{
		@Override
		public void onBinaryMessage(byte[] payload)
		{}
		@Override
		public void onClose(int code,String reason)
		{
			Log.e("ws","ws closed");
			notifyStatusChanged(status.disconnected);
		}
		@Override
		public void onOpen()
		{
			Log.e("ws","ws opened");
			m_wsc.sendTextMessage(m_login_req.getJSON().toString());
		}
		@Override
		public void onRawTextMessage(byte[] payload)
		{}
		@Override
		public void onTextMessage(String payload)
		{
			Log.e("ws","ws text message : "+payload);
			m_login_res = new ws_ans(payload,m_current_name,m_current_pass);
			notifyConnectRes(m_login_res);
		}
	};
	private Thread m_connect_thread = null;
	public enum status
	{
		disconnected,
		connecting,
		connected,
	};
	public status getStatus()
	{
		return this.m_status;
	}
	public void registerForStatusChanged(notify_node node)
	{
		m_state_changed_client_list.add(node);
		notifyStatusChanged(m_status);
	}
	private void notifyStatusChanged(status new_status)
	{
		if(m_status == new_status)
		{
			return;
		}
		switch(new_status)
		{
			case disconnected:
			{
				m_login_req = null;
				m_login_res = null;
				m_current_name = null;
				m_current_pass = null;
			}break;
			case connecting:
			{}break;
			case connected:
			{}break;
		}
		m_status = new_status;
		Message msg = null;
		for(notify_node node:m_state_changed_client_list)
		{
			msg = node.m_handler.obtainMessage(node.m_mesage);
			msg.obj = m_status;
			msg.sendToTarget();
		}
	}
	private websocket_adapter(Context context)
	{
		this.setContext(context);
		m_wsc = new WebSocketConnection();
	}
	private void notifyConnectRes(ws_ans res)
	{
		if(null == res || !res.m_result.statusCode.equals("0"))
		{
			notifyStatusChanged(status.disconnected);
		}
		if(null != res && res.m_result.statusCode.equals("0"))
		{
			notifyStatusChanged(status.connected);
		}
		Message msg = null;
		int statusCode = Integer.parseInt(res.m_result.statusCode);
		for(notify_node node:m_conncet_req_client_list)
		{
			msg = node.m_handler.obtainMessage(node.m_mesage);
			msg.arg1 = statusCode;
			msg.obj = res;
			msg.sendToTarget();
		}
		m_conncet_req_client_list.clear();
	}
	public status connect(String name,String pass,notify_node res)
	{
		m_conncet_req_client_list.add(res);
		switch (m_status)
		{	
			case disconnected:
			{
				notifyStatusChanged(status.connecting);
				m_current_name = name;
				m_current_pass = pass;
				m_connect_thread = new Thread
				(
					new Runnable()
					{
						public void run()
						{
							notifyStatusChanged(status.connecting);
							LogInStruct login_res = m_http.login(m_current_name,m_current_pass);
							if(null == login_res || login_res.result.statusCode.compareTo("0") != 0)
							{
								notifyConnectRes(null);
								return;
							}
							m_session_id = login_res.data.sessionId;
							m_login_req = new ws_login_req(m_session_id);
							Log.e("ws","http,session id:" + m_session_id);
							try 
							{
								m_wsc.connect(ws_address, m_ws_handler);
							} catch (WebSocketException e) 
							{
								// TODO Auto-generated catch block
								e.printStackTrace();
								notifyConnectRes(null);
								return;
							}
							return;
						}
					}
				);
				m_connect_thread.start();
			}break;
			case connecting:
			{}break;
			case connected:
			{
				notifyConnectRes(m_login_res);
			}break;
			
		}
		return m_status;
	}
	private void setContext(Context context)
	{
		this.m_context = context;
	}
	public static websocket_adapter getInstance(Context context)
	{
		if(null == m_instance)
		{
			m_instance = new websocket_adapter(context);
		}else
		{
			m_instance.setContext(context);
		}
		return m_instance;
	}
	
}
